package com.boil.qz.safekavass.web.interceptor;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.boil.qz.safekavass.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.boil.pojo.ResultVo;
import com.boil.util.Constants;
import com.boil.util.FastJsonUtils;

/**
 * Created by ChenYong on 2017-04-14.
 * <br>
 * 登录拦截器。
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {
    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
    /**
     * 登录 URL
     */
    private static final String LOGIN_URL = "/web/login.html";

    /**
     * 在处理请求之前被调用。
     * <ol>
     * <li>返回 true，表示继续执行下一个拦截器；</li>
     * <li>返回 false，表示中断流程，不继续执行后面的拦截器。</li>
     * </ol>
     *
     * @param request  请求
     * @param response 响应
     * @param handler  处理实例
     */
    @Override
    public boolean preHandle(HttpServletRequest request, //
                             HttpServletResponse response, //
                             Object handler) throws Exception {
        // 获取 HttpSession
        HttpSession session = request.getSession();
        // 获取登录用户
        LoginUser loginUser = (LoginUser) session.getAttribute(Constants.LOGIN_USER);

        // 如果用户未登录，则跳转至登录界面
        if (loginUser == null) {
            // Ajax 请求
            if (Constants.AJAX_REQUEST.equalsIgnoreCase(request.getHeader(Constants.REQUEST_TYPE))) {
                log.error("Ajax 请求--->用户未登录或登录超时，已被拦截！");

                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

                // 结果
                ResultVo resultVo = new ResultVo();
                resultVo.setResultCode(Constants.LOGIN_TIMEOUT);
                resultVo.setResultMsg(Constants.LOGIN_TIMEOUT_MSG);

                PrintWriter pw = null;

                try {
                    response.getWriter().write(FastJsonUtils.bean2Json(resultVo));
                } catch (Exception e) {
                    log.error("Ajax 请求--->响应用户未登录或登录超时时出现异常，异常信息如下：{}", e);
                } finally {
                    try {
                        if (pw != null) {
                            pw.close();
                        }
                    } catch (Exception e) {
                        log.error("Ajax 请求--->响应用户未登录或登录超时，关闭响应流时出现异常，异常信息如下：{}", e);
                    }
                }

                // 非 Ajax 请求
            } else {
                // 请求来自 Uploadifive 文件上传
                if (Constants.UPLOADIFIVE.equals(request.getParameter(Constants.UPLOADIFIVE))) {
                    log.error("Uploadifive 文件上传请求--->用户未登录或登录超时，已被拦截！");

                    // response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

                    // 结果
                    ResultVo resultVo = new ResultVo();
                    resultVo.setResultCode(Constants.LOGIN_TIMEOUT);
                    resultVo.setResultMsg(Constants.LOGIN_TIMEOUT_MSG);

                    PrintWriter pw = null;

                    try {
                        response.getWriter().write(FastJsonUtils.bean2Json(resultVo));
                    } catch (Exception e) {
                        log.error("Uploadifive 文件上传请求--->响应用户未登录或登录超时时出现异常，异常信息如下：{}", e);
                    } finally {
                        try {
                            if (pw != null) {
                                pw.close();
                            }
                        } catch (Exception e) {
                            log.error("Uploadifive 文件上传请求--->响应用户未登录或登录超时，关闭响应流时出现异常，异常信息如下：{}", e);
                        }
                    }

                    // 普通请求
                } else {
                    log.error("非 Ajax 请求--->用户未登录或登录超时，已被拦截，跳转至登录页面！");

                    response.sendRedirect(String.format("%s%s", request.getContextPath(), LOGIN_URL));
                }
            }

            return false;
        }

        return true;
    }

    /**
     * 后处理回调方法，实现处理器的后处理（但在渲染视图之前），此时我们可以通过 modelAndView（模型和视图对象）
     * 对模型数据进行处理或对视图进行处理，modelAndView 也可能为 null。
     *
     * @param request      请求
     * @param response     响应
     * @param handler      处理实例
     * @param modelAndView 模型视图
     */
    @Override
    public void postHandle(HttpServletRequest request, //
                           HttpServletResponse response, //
                           Object handler, //
                           ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 整个请求处理完毕回调方法，即在视图渲染完毕时回调，如性能监控中我们可以在此记录结束时间并输出消耗时间，
     * 还可以进行一些资源清理，类似于 try-catch-finally 中的finally，
     * 但仅调用处理器执行链中 preHandle 返回 true 的拦截器的 afterCompletion。
     *
     * @param request  请求
     * @param response 响应
     * @param handler  处理实例
     * @param ex       异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, //
                                HttpServletResponse response, //
                                Object handler, //
                                Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
}